﻿using ETask.Api.Data;
using ETask.Api.Dtos;
using ETask.Api.Models;

namespace ETask.Api.Repositories
{
    public class ProjectTaskRepository : Repository<ProjectTask>, IProjectTaskRepository
    {
        public ProjectTaskRepository(AppDbContext context) : base(context)
        {
        }

        public async Task<PagedResult<ProjectTaskDto>> GetListAsync(ProjectTaskListParams listParams)
        {
            var query = _context.ProjectTasks
                .GroupJoin(_context.Users,
                    task => task.CreateBy,
                    user => user.Id,
                    (task, createUsers) => new { task, createUsers })
                .SelectMany(
                    combined => combined.createUsers.DefaultIfEmpty(),
                    (combined, createUser) => new { combined.task, createUser })
                .GroupJoin(_context.Users,
                    combined => combined.task.AssignedTo,
                    user => user.Id,
                    (combined, assignedUsers) => new { combined.task, combined.createUser, assignedUsers })
                .SelectMany(
                    combined => combined.assignedUsers.DefaultIfEmpty(),
                    (combined, assignedUser) => new { combined.task, combined.createUser, assignedUser })
                .GroupJoin(_context.Users,
                    combined => combined.task.UpdateBy,
                    user => user.Id,
                    (combined, updatedUsers) => new { combined.task, combined.createUser, combined.assignedUser, updatedUsers })
                .SelectMany(
                    combined => combined.updatedUsers.DefaultIfEmpty(),
                    (combined, updatedUser) => new {
                        task = combined.task,
                        createUser = combined.createUser,
                        assignedUser = combined.assignedUser,
                        updatedUser = updatedUser
                    });
            if (listParams.IsMy)
            {
                LoginUser login = UserContext.CurrentUser;
                query = query.Where(q => q.task.AssignedTo == login.Id);
            }

            query = query.Where(item => item.task.ProjectId == listParams.ProjectId);
            if (!string.IsNullOrWhiteSpace(listParams.KeyWord))
            {
                var keyword = listParams.KeyWord.Trim();
                query = query.Where(item =>
                    item.task.Description.Contains(keyword) ||
                    item.assignedUser.Name.Contains(keyword) ||
                    item.createUser.Name.Contains(keyword));
            }

            if (listParams.Status.HasValue)
            {
                query = query.Where(item => item.task.Status == listParams.Status.Value);
            }

            if (listParams.BeginTime.HasValue)
            {
                query = query.Where(item => item.task.BeginDate >= listParams.BeginTime.Value);
            }
            if (listParams.EndTime.HasValue)
            {
                query = query.Where(item => item.task.BeginDate <= listParams.EndTime.Value);
            }

            if (listParams.DueBeginTime.HasValue)
            {
                query = query.Where(item => item.task.DueDate >= listParams.DueBeginTime.Value);
            }
            if (listParams.DueEndTime.HasValue)
            {
                query = query.Where(item => item.task.DueDate <= listParams.DueEndTime.Value);
            }

            var resultQuery = query
                .OrderByDescending(item => item.task.BeginDate)
                .Select(item => new ProjectTaskDto
                {
                    Id = item.task.Id,
                    CreateBy = item.task.CreateBy,
                    CreatedAt = item.task.CreatedAt,
                    CreateByName = item.createUser.Name,
                    UpdateBy = item.task.UpdateBy,
                    UpdatedAt = item.task.UpdatedAt,
                    UpdateByName = item.updatedUser.Name,
                    ProjectId = item.task.ProjectId,
                    Description = item.task.Description,
                    AssignedTo = item.task.AssignedTo,
                    AssignedToName = item.assignedUser.Name,
                    BeginDate = item.task.BeginDate,
                    DueDate = item.task.DueDate,
                    Status = item.task.Status,
                    ActualEndDate = item.task.ActualEndDate
                });

            return await resultQuery.ToPagedResultAsync(listParams.PageDto);
        }
    }
}
